<?php

include "classes/fuzzy.class.php";


class Viability {

    #private $values;

    private $plausibilityValues = array();
    private $fitnessValues      = array(); #adecuacion
    private $justificationValues= array();
    private $successValues      = array();

    private $plausibilityWeight;
    private $fitnessWeight; #adecuacion
    private $justificationWeight;
    private $successWeight;



    private $plausibility;
    private $fitness; #adecuacion
    private $justification;
    private $success;

    public function __construct($values){

        global $CHARACTERISTICS;

        // Fill in characteristic values
        foreach ($values as $id => $value){

            $characteristic = clone  $CHARACTERISTICS[$id] ;
            $characteristic->setValue($value);
            
            $dimension = substr($characteristic->dimension,0,1);
            switch ($dimension){
                case "P":
                    $this->plausibilityValues[] = $characteristic;
                    break;
                case "A":
                    $this->fitnessValues[]      = $characteristic;
                    break;
                case "J":
                    $this->justificationValues[]  = $characteristic;
                    break;
                case "E":
                    $this->successValues[]        = $characteristic;
                    break;
            }
        }


        // Do the math
        $this->plausibility  = $this->calcPlausibility();
        $this->fitness       = $this->calcFitness();
        $this->justification = $this->calcJustification();
        $this->success       = $this->calcSuccess();

        
        $this->plausibilityWeight   = FuzzyValue::fromNumeric(8);
        $this->fitnessWeight        = FuzzyValue::fromNumeric(8);
        $this->justificationWeight  = FuzzyValue::fromNumeric(3);
        $this->successWeight        = FuzzyValue::fromNumeric(5);

        $this->finalResult = $this->calcFinalResult();
        



    }

    public function getFinalResult(){
        return $this->finalResult;
    }

    public function getFinalResultAvg(){
        return $this->finalResult->avg();
    }
 
    public function getPlausibility (){
        return $this->plausibility ;
    }

    public function getFitness (){
        return $this->fitness ;
    }

    public function getJustification (){
        return $this->justification ;
    }

    public function getSuccess (){
        return $this->success ;
    }


    /*************************************************************************/



    private function calcFinalResult() {

        $sum1 = new FuzzyValue(0,0,0,0);
        $sum2 = new FuzzyValue(0,0,0,0);

        $sum1 = $sum1->add( $this->plausibility->mul($this->plausibilityWeight) );
        $sum1 = $sum1->add( $this->fitness->mul($this->fitnessWeight) );
        $sum1 = $sum1->add( $this->justification->mul($this->justificationWeight) );
        $sum1 = $sum1->add( $this->success->mul($this->successWeight) );


        $sum2 = $sum2->add( $this->plausibilityWeight);
        $sum2 = $sum2->add( $this->fitnessWeight);
        $sum2 = $sum2->add( $this->justificationWeight);
        $sum2 = $sum2->add( $this->successWeight);
    

        $result = $sum1->div($sum2);
        return $result;
    }

    
    private function calcPlausibility(){
        $armMean = $this->calcArmonicMean($this->plausibilityValues);
        $ariMean = $this->calcArithmeticMean($this->plausibilityValues);

        $armMean = $armMean->div(FuzzyValue::fromNumeric(2));
        $ariMean = $ariMean->div(FuzzyValue::fromNumeric(2));

        $result = $armMean->add($ariMean);
        return $result;

    }

    private function calcFitness(){
        $armMean = $this->calcArmonicMean($this->fitnessValues);
        $ariMean = $this->calcArithmeticMean($this->fitnessValues);

        $armMean = $armMean->div(FuzzyValue::fromNumeric(2));
        $ariMean = $ariMean->div(FuzzyValue::fromNumeric(2));

        $result = $armMean->add($ariMean);
        return $result;
    }


    #TODO TODO TODO
    # este calculo es distinto!!! leer como se hace!

#    private function calcJustification(){
#        
#	$armMean = $this->calcArmonicMean($this->justificationValues);
#        $ariMean = $this->calcArithmeticMean($this->justificationValues);
#
#        $armMean = $armMean->div(FuzzyValue::fromNumeric(2));
#        $ariMean = $ariMean->div(FuzzyValue::fromNumeric(2));
#
#        $result = $armMean->add($ariMean);
#        return $result;
#    }
    private function calcJustification(){
        
        $values = $this->justificationValues;

	$max=0;
	foreach ($values as $p){

            $weight = FuzzyValue::fromNumeric($p->weight);
            $result = $weight->mul($p->getValue());
	    $average = $result->avg();
		
		if ($average > $max) {
			$max = $average;
		}
        }

        $result = FuzzyValue::fromNumeric($max);
        $res = $result->div(FuzzyValue::fromNumeric(10));
        return $res;
    }


    private function calcSuccess(){
        $armMean = $this->calcArmonicMean($this->successValues);
        $ariMean = $this->calcArithmeticMean($this->successValues);

        $armMean = $armMean->div(FuzzyValue::fromNumeric(2));
        $ariMean = $ariMean->div(FuzzyValue::fromNumeric(2));

        $result = $armMean->add($ariMean);
        return $result;


    }


    private function calcArmonicMean($values){
       
        $weightSum = new FuzzyValue(0,0,0,0);
        $weightOverValueSum = new FuzzyValue(0,0,0,0);

        foreach ($values as $p){
            $weightSum = $weightSum->add(FuzzyValue::fromNumeric($p->weight));

        }
        
        foreach ($values as $p){
            $weight = FuzzyValue::fromNumeric($p->weight);
            $tmp = $weight->div($p->getValue());
            $weightOverValueSum = $weightOverValueSum->add($tmp);
        }


        $result = $weightSum->div($weightOverValueSum);

        return $result;
    }


    private function calcArithmeticMean($values){
       
        $weightSum = new FuzzyValue(0,0,0,0);
        $weightByValueSum = new FuzzyValue(0,0,0,0);

        foreach ($values as $p){
            $weightSum = $weightSum->add(FuzzyValue::fromNumeric($p->weight));

        }

        
        foreach ($values as $p){

            $weight = FuzzyValue::fromNumeric($p->weight);
            $tmp = $weight->mul($p->getValue());
            $weightByValueSum = $weightByValueSum->add($tmp);

        }

        $result = $weightByValueSum->div($weightSum);

        return $result;
    }

}
?>
